/**
 * Copyright (c) 2010 Jesco Freund.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * 3. Neither the name of Backtory nor the names of its contributors may be used
 *    to endorse or promote products derived from this software without
 *    specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $Id$
 */


#ifdef BY_ERROR_H
#undef BY_ERROR_H
#endif
#define BY_ERROR_NAMES
#include "backtory/error.h"
#undef BY_ERROR_NAMES

#include <stdlib.h>
#include <errno.h>
#include <string.h>

#include "config.h"


int
__by_strerror_r(char *buffer, size_t bufsize, int error)
{
	int rval = 0;
	
	by_edesc_t *e = by_errlist;
	while ((e->description) && (e->code != error))
		e++;
	
	memset(buffer, (int)'\0', bufsize);
	if (e->description)
	{
		strncpy(buffer, (char *)e->description, (strlen((char *)e->description) > (bufsize - 1) ? (bufsize -1) : strlen((char *)e->description)));
		if (strlen(e->description) > (bufsize -1))
			rval = ERANGE;
	}
	else
	{
		strncpy(buffer, "unknown error", 14 > (bufsize - 1) ? (bufsize - 1) : 14);
		rval = EINVAL;
	}
	return rval;
}


extern int
by_strerror_r(int errnum, char *buffer, size_t bufsize)
{
	int rval = 0;
#if defined(HAVE_POSIX_STRERROR_R)
	rval = strerror_r(errnum, buffer, bufsize);
	if (rval != 0)
		rval = __by_strerror_r(buffer, bufsize, errnum);
#elif defined(HAVE_GLIBC_STRERROR_R)
	if (errnum >= E_PSEUDOBASE)
	{
		rval = __by_strerror_r(buffer, bufsize, errnum);
	}
	else
	{
		char mbuffer[256];
		char *msg = strerror_r(errnum, mbuffer, sizeof(mbuffer));
		strncpy(buffer, msg, bufsize);
		if (strlen(msg) > (bufsize - 1))
			rval = ERANGE;
	}
#endif
	return rval;
}
